'''
FUba PLC通讯 业务逻辑

'''
import threading
import time
import traceback

# sys.path.append(r'D:\code\huoNiWeiEr\project_huoni_v2\neith_fyluoding\plc_S7')
# from plc_S7.s7_client import lay1_client
# 导入layer1_client
try:
    from plc_client.layer1.factory import Lay1PLCFactory
except:
    from ..layer1.factory import Lay1PLCFactory

# 导入ABCProjectPlcClient
try:
    from plc_client.layer2.ABCProjectPlcClient import ProjectPlcClient
except:
    from ..layer2.ABCProjectPlcClient import ProjectPlcClient

try:
    from log import logger
except:
    from ...log import logger




class FubaPlcClient(ProjectPlcClient): # 一个点位一个plc客户端 （各点位plc逻辑类似）
    def __init__(self, lay1_client_name = 'modbus_tcp' ):
        super().__init__()
        config = {
            'ip': '192.168.250.1',
            'port': 44818,
            'dbnumber': 183,
            'name_addr_dict': { # 地址格式和plc layer1有关
                'p1.is_jc': 'giPress_VisionStart', # 检测触发
                'p1.jc_res':'giPress_VisionResult', # 检测结果
                # 'p2.is_jc':'giPress_VisionStart', # 检测触发
                # 'p2.jc_res':10,
                'is_ready': 0,
                'giPress_VisionMode':'giPress_VisionMode', # 检测步骤
                'giPress_VisionHeartbeat': 'giPress_VisionHeartbeat',# 心跳
                'bar_str': ['giPress_VisionCodeA1', 'giPress_VisionCodeA2',
                            'giPress_VisionCodeA3', 'giPress_VisionCodeA4',
                            'giPress_VisionCodeA5', 'giPress_VisionCodeA6',
                            'giPress_VisionCodeA7', 'giPress_VisionCodeA8'], # 条码 12345678
                'gstrProgramName': 'gstrProgramName', # 产品型号
            }
            
        }
        self.config = config
        self.lay1_client = Lay1PLCFactory.create(lay1_client_name, config['ip'], config['port']) # 可根据lay1_client_name选择对象
        # self.lay1_client = lay1_client_class(config['ip'], config['port'])
        self.lock = threading.Lock() # 同步

    def connect(self):
        self.lay1_client.connect()

    def close(self):
        self.lay1_client.close()

    def isConnected(self):
        return self.lay1_client.get_connected()

    def wait_plc(self, get_trigger_signal, set_zero_trigger_signal, var_name='p1.is_jc',
                 is_continue_fun_1=None, get_step_mode_fun = None):  # self.get_is_scan_done, set_zero_is_scan_done
        '''
        usage:
        self.wait(self.get_is_scan_done, self.set_zero_is_scan_done)
        :param get_chufa_fun1:
        :param set_zeros_fun2:
        is_continue_fun_1: break when is_continue_fun_1 is false， 额外的结束等待条件
        get_step_mode_fun: 获取触发时的检测步骤

        :return: int
        '''
        isDone = 0  # 1 ture 2 false
        # 等待触发
        while isDone == 0:
            isDone = get_trigger_signal(var_name)  #
            if is_continue_fun_1 is not None and not is_continue_fun_1():  # break when is_continue_fun_1 is false
                break
            time.sleep(0.1)  # s
        set_zero_trigger_signal(var_name)  # to 0
        # 获取检测步骤
        if get_step_mode_fun is not None:
            return get_step_mode_fun()
        print(f"{var_name} isDone {isDone}")
        return 0

    def set_is_ready(self, is_ready):
        self.lock.acquire()
        self.lay1_client.write_int8(start=self.config['name_addr_dict']['is_ready'], data_int8=is_ready)
        self.lock.release()

    def get_trigger_signal(self, var_name='p1.is_jc'):  # 是否引导
        try:
            self.lock.acquire()
            is_yd = self.lay1_client.read_int8(start=self.config['name_addr_dict'][var_name])
            self.lock.release()
        except Exception as e:
            self.lock.release()
            logger.error(traceback.format_exc())
            self.lock.acquire()
            self.close()
            logger.info('re connecting')
            self.connect() # 重连
            logger.info('re connecting done')
            self.lock.release()
            return 0

        return is_yd

    def set_zero_trigger_signal(self, var_name='p1.is_jc'):  # 是否引导 置0
        self.lock.acquire()
        self.lay1_client.write_int8(start=self.config['name_addr_dict'][var_name], data_int8=0)
        self.lock.release()
        return


    def set_res(self, yd_res, var_name='p1.jc_res'):  # 引导结果
        self.lock.acquire()
        try:
            # pass
            self.lay1_client.write_int8(start=self.config['name_addr_dict'][var_name], data_int8=yd_res)
        except Exception as e:
            self.lock.release()
            print('发送引导结果失败')
            print(e)
        self.lock.release()


    def get_step_mode(self, var_name='giPress_VisionMode'): # 获取检测步骤
        self.lock.acquire()
        is_yd = self.lay1_client.read_int8(start=self.config['name_addr_dict'][var_name])
        self.lock.release()
        return is_yd

    def heart_work_thread(self):
        '''
        心跳线程
        '''
        var_name = 'giPress_VisionHeartbeat'
        value = 0
        while True:
            try:
                value = 0 if value == 1 else 1
                self.lay1_client.write_int8(start=self.config['name_addr_dict'][var_name], data_int8=value)
                print(f'plc heartbeat {value} {time.time()}')
                time.sleep(1)
            except:
                self.close()
                self.connect()

    def set_manual_trigger(self, var_name_trigger='p1.is_jc', var_name_step_mode='giPress_VisionMode', step_mode=0):
        self.lay1_client.write_int8(start=self.config['name_addr_dict'][var_name_step_mode], data_int8=step_mode) # 检测步骤
        self.lay1_client.write_int8(start=self.config['name_addr_dict'][var_name_trigger], data_int8=1) # 触发置1

    def write_string(self, var_name='bar_str', value='123'):
        self.lay1_client.write_string(start=self.config['name_addr_dict'][var_name],data_str=value)

    def read_string(self, var_name='gstrProgramName'): # 20240725 产品型号
        return self.lay1_client.read_string(start=self.config['name_addr_dict'][var_name])

    # def read_string(self, var_name='product_name'):
    #     pass

    def set_heart(self, var_name='var_name', value=0): # 设置心跳

        self.lay1_client.write_int8(start=self.config['name_addr_dict'][var_name], data_int8=value)

def test_FubaPlcClient():

    hn_plc = FubaPlcClient(lay1_client_name='eth_ip_cip')
    hn_plc.connect()
    hn_plc.write_string(var_name='bar_str', bar_str='12345678')
    numb = hn_plc.read_string()
    print(numb)
    hn_plc.close()


if __name__ == "__main__":
    # test_HuoniPlcClinet()
    test_FubaPlcClient()
